package com.tgh.gles2.c5.tunnel;

import com.tgh.gles2.R;
import com.tgh.utils.GLBatch;
import com.tgh.utils.GLFrustum;
import com.tgh.utils.GLGeometryTransform;
import com.tgh.utils.GLMatrixStack;
import com.tgh.utils.GLShaderManager;
import com.tgh.utils.GLShaderManager.ShaderType;
import com.tgh.utils.GLTools;

import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class MySurfaceView extends GLSurfaceView {

    public MySurfaceView(Context context) {
        super(context);
        init();
    }

    public MySurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    
    public void moveForward() {
        viewZ+=0.5f;
        requestRender();
    }
    
    public void moveBack() {
        viewZ-=0.5f;
        requestRender();
    }
    
    
    private void init() {
        setEGLContextClientVersion(2);
        setRenderer(new SceneRenderer());
        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
    }
    
    private float viewZ=-60.f;
    
    private class SceneRenderer implements Renderer{

        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            initTextures();
            initData();
            shaderManager = new GLShaderManager();
            shaderManager.initStockShader();
            modelViewMatrix = new GLMatrixStack();
            projectionMatrix = new GLMatrixStack();
            transformPipleline = new GLGeometryTransform();
            GLES20.glClearColor(0, 0, 0, 1);
        }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            GLES20.glViewport(0, 0, width, height);
            viewFrustum = new GLFrustum(80, (float)width/(float)height, 1, 120);
            projectionMatrix.loadMatrix(viewFrustum.getProjectionMatrix());
            transformPipleline.setMatrixStack(modelViewMatrix, projectionMatrix);
        }

        @Override
        public void onDrawFrame(GL10 gl) {
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
            modelViewMatrix.pushMatrix();
                modelViewMatrix.translate(0, 0, viewZ);
                shaderManager.useStockShader(ShaderType.TEXTURE_REPLACE, transformPipleline.getModelViewProjectionMatrix().getArray(),0);
                GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[1]);
                floorBatch.draw();
                GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[2]);
                ceilBatch.draw();
                GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
                leftWallBatch.draw();
                rightWallBatch.draw();
            modelViewMatrix.popMatrix();
        }
        
        private void initTextures() {
            textures = GLTools.genTextures(3);
            
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
             GLTools.loadDrawableToTexture2D(getContext(), R.drawable.brick, 
                    GLES20.GL_LINEAR_MIPMAP_LINEAR, GLES20.GL_NEAREST, GLES20.GL_CLAMP_TO_EDGE, true,true);
             
             GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[1]);
             GLTools.loadDrawableToTexture2D(getContext(), R.drawable.floor, 
                    GLES20.GL_LINEAR_MIPMAP_LINEAR, GLES20.GL_NEAREST, GLES20.GL_CLAMP_TO_EDGE, true,true);
            
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[2]);
            GLTools.loadDrawableToTexture2D(getContext(), R.drawable.ceiling, 
                    GLES20.GL_LINEAR_MIPMAP_LINEAR, GLES20.GL_NEAREST, GLES20.GL_CLAMP_TO_EDGE, true,true);
        }
        
        private void initData() {
            floorBatch = new GLBatch(GLES20.GL_TRIANGLE_STRIP, 28);
            for(float z=60;z>=0;z-=10){
                floorBatch.multiTexCoord(0, 0.0f, 0.0f);
                floorBatch.vertex(-10, -10, z);
                
                floorBatch.multiTexCoord(0, 1.0f, 0.0f);
                floorBatch.vertex(10, -10, z);
                
                floorBatch.multiTexCoord(0, 0.0f, 1.0f);
                floorBatch.vertex(-10, -10, z-10.0f);
                
                floorBatch.multiTexCoord(0, 1.0f, 1.0f);
                floorBatch.vertex(10, -10, z-10.0f);
            }
            floorBatch.end();
            
            ceilBatch = new GLBatch(GLES20.GL_TRIANGLE_STRIP, 28);
            for(float z=60;z>=0;z-=10){
                ceilBatch.multiTexCoord(0, 0.0f, 1.0f);
                ceilBatch.vertex(-10, 10, z-10.0f);
                
                ceilBatch.multiTexCoord(0, 1.0f, 1.0f);
                ceilBatch.vertex(10, 10, z-10.0f);
                
                ceilBatch.multiTexCoord(0, 0.0f, 0.0f);
                ceilBatch.vertex(-10, 10, z);
                
                ceilBatch.multiTexCoord(0, 1.0f, 0.0f);
                ceilBatch.vertex(10, 10, z);
            }
            ceilBatch.end();
            
            leftWallBatch = new GLBatch(GLES20.GL_TRIANGLE_STRIP, 28);
            for(float z=60;z>=0;z-=10){
                leftWallBatch.multiTexCoord(0, 0.0f, 0.0f);
                leftWallBatch.vertex(-10, -10, z);
                
                leftWallBatch.multiTexCoord(0, 0.0f, 1.0f);
                leftWallBatch.vertex(-10, 10, z);
                
                leftWallBatch.multiTexCoord(0, 1.0f, 0.0f);
                leftWallBatch.vertex(-10, -10, z-10.0f);
                
                leftWallBatch.multiTexCoord(0, 1.0f, 1.0f);
                leftWallBatch.vertex(-10, 10, z-10.0f);
            }
            leftWallBatch.end();
            
            rightWallBatch = new GLBatch(GLES20.GL_TRIANGLE_STRIP, 28);
            for(float z=60;z>=0;z-=10){
                rightWallBatch.multiTexCoord(0, 0.0f, 0.0f);
                rightWallBatch.vertex(10, -10, z);
                
                rightWallBatch.multiTexCoord(0, 0.0f, 1.0f);
                rightWallBatch.vertex(10, 10, z);
                
                rightWallBatch.multiTexCoord(0, 1.0f, 0.0f);
                rightWallBatch.vertex(10, -10, z-10.0f);
                
                rightWallBatch.multiTexCoord(0, 1.0f, 1.0f);
                rightWallBatch.vertex(10, 10, z-10.0f);
            }
            rightWallBatch.end();
        }
        
        private GLBatch floorBatch;
        private GLBatch ceilBatch;
        private GLBatch leftWallBatch;
        private GLBatch rightWallBatch;
        private GLShaderManager shaderManager;
        private GLFrustum viewFrustum;
        private GLMatrixStack modelViewMatrix;
        private GLMatrixStack projectionMatrix;
        private GLGeometryTransform transformPipleline;
    }
    private int[] textures;
}
